package n30_保护共享资源_加锁和不加锁实现;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author fu
 * @date 2022-01-27 21:17
 * 概要：
 */
public class TestAccount {

    public static void main(String[] args) {
//        Account.demo(new AccountUnsafe(10000));


        // 不加锁 保护线程共享数据安全 实现
        Account.demo(new AccountCas(10000));
    }

}
/*
 * ---------------------------------------------------------------
 * |                                                             |
 * |               保护共享资源 --- 不加锁实现                      |
 * |                                                             |
 * |=============================================================
 */
class AccountCas implements Account{
    // jdk提供的 原子整数
    private AtomicInteger balance;


    public AccountCas(int balance) {
        this.balance = new AtomicInteger(balance);
    }

    @Override
    public Integer getBalance() {
        return balance.get();
    }

/*    @Override
    public void withdraw(Integer amount) {

        while(true) {
            // 获取余额最新值
            int prev = balance.get();     // 这里是局部变量 是运行在线程的 工作内存上
            // 修改余额
            int next = prev - amount;     // 这里是局部变量 是运行在线程的 工作内存上

            // 同步到 主存中 去 【 --- 前提：先将prev与对象里最新值进行比较，[如果相同 则设置] --- 】
            if (balance.compareAndSet(prev, next)) {
                break;
            }
        }
    }*/

    @Override
    public void withdraw(Integer amount) {

       balance.getAndAdd(-1 * amount);
    }
}

/*
 * ---------------------------------------------------------------
 * |                                                             |
 * |               保护共享资源 --- 加锁实现                      |
 * |                                                             |
 * |=============================================================
 */
class AccountUnsafe implements Account {

    private Integer balance;
    public AccountUnsafe(Integer balance) {
        this.balance = balance;
    }

    @Override
    public Integer getBalance() {
        synchronized (this) {
            return balance;
        }
    }
    // 共享资源变量 加锁
    @Override
    public void withdraw(Integer amount) {
        synchronized (this) {
            balance -= amount;
        }
    }

}



interface Account {
    // 获取余额
    Integer getBalance();
    // 取款
    void withdraw(Integer amount);
    /**
     * 方法内会启动 1000 个线程，每个线程做 -10 元 的操作
     * 如果初始余额为 10000 那么正确的结果应当是 0
     */
    static void demo(Account account) {
        List<Thread> ts = new ArrayList<>();
        long start = System.nanoTime();

        for (int i = 0; i < 1000; i++) {
            ts.add(new Thread(() -> {
                account.withdraw(10);
            }));
        }

        ts.forEach(Thread::start);
        ts.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        long end = System.nanoTime();
        System.out.println("最终余额 = " + account.getBalance()
                + " 。 执行时间cost= " + (end-start)/1000_000 + " ms");
    }
}
